package com.qf.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.cache.CategoryCache;
import com.qf.cache.SceneCache;
import com.qf.events.CommandEvent;
import com.qf.exeptions.AddDataException;
import com.qf.exeptions.QueryDataException;
import com.qf.exeptions.ResultCode;
import com.qf.mappers.DeviceMapper;
import com.qf.pojo.*;
import com.qf.service.DeviceService;
import com.qf.utils.SecurityUtils;
import com.qf.websocket.MyCommandHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.sound.midi.Soundbank;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/*
杨威
2022/1/5
12:23
*/
@Service
@Transactional
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    CategoryCache categoryCache;
    @Autowired
    SceneCache sceneCache;
    @Override
    public void addDevice(Device device) {
        Assert.isTrue(!device.isEmpty(CheckType.ADD),()->{
            throw new AddDataException("数据不完整", ResultCode.DATA_EMPTY);
        });

        //查看设备是否被别人绑定了
        Device select = deviceMapper.selectByDeviceId(device.getDeviceId());

        device.setBindUserId(10l);
        Assert.isTrue(select==null,()->{
            throw new AddDataException("设备已被别人绑定",ResultCode.DEVICE_ALREADY_BIND);
        });

        device.setIsOnline(2l);
        Assert.notNull(categoryCache.getValue(device.getCategyId()),()->{
            throw new AddDataException("分类不存在", ResultCode.DATA_NOT_EXIST);
        });
        //如果没传场景 给一个默认场景
        if(device.getSceneId()==null){
            device.setSceneId(-1l);
        }
        //传了场景 我们要判断这个场景是否存在
        if(device.getSceneId()!=-1){
            List<Scene> sceneList=null;
            try {
                sceneList = sceneCache.getSceneLoadingCache().get(10l);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            Assert.isTrue(sceneList.stream().map(Scene::getSceneId).collect(Collectors.toList()).contains(device.getSceneId()),()->{
                throw new AddDataException("场景不存在",ResultCode.DATA_NOT_EXIST);
            });
        }
        device.setBindTime(new Date());
        deviceMapper.addDevice(device);
    }

    @Override
    public void sendController(String id, String command) throws JsonProcessingException {
        //我们不能向其他人设备发命令
        Device device = findById(id);
        Assert.notNull(device,()->{
            throw new QueryDataException("没有对应的设备", ResultCode.DEVICE_NOT_EXIST);
        });
        User user = SecurityUtils.getUser();
        //比较设备的绑定者是不是自己
        Assert.isTrue(device.getBindUserId()==user.getUId(),()->{
            throw new QueryDataException("当前设备不属于你", ResultCode.DEVICE_CONTROL_NOTALLOWED);
        } );
        //看看设备是否在线
        Assert.isTrue(device.getIsOnline()==1,()->{
            throw new QueryDataException("设备不在线", ResultCode.DEVICE_OFFLINE);
        });
        //获取设备的分类 然后获取上行的命令 也就是相对于服务器 发给设备的命令
        Long categyId = device.getCategyId();
        Category category = categoryCache.getValue(categyId);
        String txCommand = category.getTxCommand();
        ObjectMapper objectMapper=new ObjectMapper();
        //解析json成一个map
        Map commandMap = objectMapper.readValue(txCommand, Map.class);
        Map targetCommandMap = (Map) commandMap.get(command);
        //需要发送给设备的命令
        Object finalCommand = targetCommandMap.get("command");
        MyCommandHandler.sendControl(new CommandEvent(id,finalCommand));
    }

    @Override
    public void updateDeviceOnlineStaus(Device device) {
        if(device.getIsOnline()==1){
            deviceMapper.updateOnLine(device);
        }else {
            deviceMapper.updateOffLine(device);
        }
    }

    public Device findById(String id){
        Assert.notNull(id,()->{
            throw new QueryDataException("没有传递主键",ResultCode.ID_NULL);
        });
        Device device = deviceMapper.selectByDeviceId(id);
        return device;
    }
}
